const htmlStr = `<head class="home" onclick="handle()"><title class="hhhh">ssssssss<div class="test_div">ffff</div></title></head>`

class domNode {
  constructor(tagName) {
    this.tagName = tagName;
    this.attrs = {}
    this.children = []
    this.innerText = ''
  }
}

const OPEN_TAG = 'openTag'
const TAGNAME_VALUING = 'tagNameValuing';
const ATTRIBUTENAME_VALUING = 'attributeNameValuing'
const ATTRIBUTEVALUE_VALUING = 'attributeValueValuing'
const CLOSE_TAG = 'closeTag'
const TEXT_TEXTVALUING = 'textValuing';
const TAG_FINISHING = 'tagFinishing';


class htmlParser {
  constructor(htmlStr = '') {
    this.tagName = '';
    this.attributeName = ''
    this.attributeValue = ''
    this.currNode = null;
    this.innerText = ''
    this.status = OPEN_TAG
    this.currentIndex = 0;
    this.htmlStr = htmlStr
    this.nodeStack = []
    this.attributeValuingStack = []
    this.attrs = {}
    this.parentNode=null;
    this.domTree=[]
  }
  parse() {
    for (this.currentIndex = 0; this.currentIndex < this.htmlStr.length; this.currentIndex++) {
      const curr = this.htmlStr[this.currentIndex];
      const next = this.htmlStr[this.currentIndex + 1];
      const pre = this.htmlStr[this.currentIndex - 1];
      console.log(curr, next, this.status)
      switch (this.status) {
        case OPEN_TAG:
          this.handleOpenTag(curr, next)
          break;
        case TAGNAME_VALUING:
          this.handleTagNameValuing(curr, next);
          break;
        case ATTRIBUTENAME_VALUING:
          this.handleAttributeNameValuing(curr, next);
          break;
        case ATTRIBUTEVALUE_VALUING:
          this.handleAttributeValueValuing(curr, next);
          break;
        case CLOSE_TAG:
          this.handleCloseTag(curr, next)
          break;
        case TAG_FINISHING:
          this.handleTagFinishing(curr, next);
          break;
        case TEXT_TEXTVALUING:
          this.handleTextValuing(curr, next);
          break;
        default:
          break;
      }
    }
  }
  handleOpenTag(curr, next) {
    if (next === '/') {
      this.status = TAG_FINISHING
      return;
    }
    if (curr === '<') {
      this.status = TAGNAME_VALUING
    }
  }
  handleTagNameValuing(curr, next) {
    this.tagName += curr;
    if (next) {
      if (!next.trim().length) {
        this.status = ATTRIBUTENAME_VALUING
      } else if (next === '>') {
        this.status = CLOSE_TAG
      }
    } else {
      console.log('finish')
    }
  }
  handleAttributeNameValuing(curr, next) {
    if (curr === '='||!curr.trim().length) {
      return;
    }
    this.attributeName += curr;
    if (curr === '"') {
      this.attributeValuingStack.push(curr)
      this.status = ATTRIBUTEVALUE_VALUING
    }
  }
  handleAttributeValueValuing(curr, next) {
    if (curr === '"') {
      if (this.getAttributeValuingStack() === curr) {
        this.attributeValuingStack.pop();
        this.attrs[this.attributeName] = this.attributeValue
        this.attributeName = ''
        this.attributeValue = ''
        if (!next.trim().length) {
          this.status = ATTRIBUTENAME_VALUING
        } else if (next === '>') {
          this.status = CLOSE_TAG;
          return;
        } else {
          throw Error('引号未闭合!')
        }
      } else {
        throw Error('引号未闭合！')
      }
      return;
    }
    this.attributeValue += curr;
  }
  handleCloseTag(curr, next) {
    this.generateDomNode()
    console.log(JSON.stringify(this.domTree))
    if (next !== '<') {
      this.status = TEXT_TEXTVALUING
    } else if (next === '<') {
      this.status = OPEN_TAG
    } else {
      return;
    }
  }
  handleTagFinishing(curr, next) {
    this.tagName += curr;
    if (next === '>') {
      if(this.nodeStack.length!==0){
        if (this.getNodeStack().tagName === this.tagName) {
          this.nodeStack.pop()
        } 
        
      }else{
        this.status=OPEN_TAG
      }
      
    }
    console.log(JSON.stringify(this.domTree),'final!')
  }
  generateDomNode() {
    if (!this.domTree.length) {
      let node = new domNode(this.tagName)
      node.attrs=this.attrs;
      node.innerText=this.innerText;
      this.currNode = node;
      this.parentNode=null;
      this.domTree.push(this.currNode)
      this.nodeStack.push(this.currNode)
    } else {
      if(this.getNodeStack()){
        if(this.getNodeStack().tagName!==this.tagName){
          let newNode=new domNode(this.tagName)
          newNode.attrs=this.attrs;
          newNode.innerText=this.innerText;
          this.parentNode=this.currNode;
          this.parentNode.children.push(newNode)
          this.currNode=newNode
        }
      }
    }
    this.attrs={}
    this.tagName=''
  }
  handleTextValuing(curr, next) {
    this.innerText += curr;
    if (next === '<') {
      this.currNode.innerText=this.innerText
      this.innerText = ''
      this.status = OPEN_TAG
    }
  }
  getNodeStack() {
    return this.nodeStack[this.nodeStack.length - 1]
  }

  getAttributeValuingStack() {
    return this.attributeValuingStack[this.attributeValuingStack.length - 1]
  }
}


const compiler = new htmlParser(htmlStr)
compiler.parse()